package com.xinqi.modules.user.rongyuntemp.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.base.enums.YesNoNumberEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.R;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.common.redis.utils.RedisUtils;
import com.xinqi.modules.chat.chat.rongyun.RemoteRongyunClient;
import com.xinqi.modules.user.rongyuntemp.config.RongYunTokenConfig;
import com.xinqi.modules.user.rongyuntemp.domain.RongYunTokenTempEntity;
import com.xinqi.modules.user.rongyuntemp.manager.RongYunTokenTempManager;
import com.xinqi.modules.user.rongyuntemp.service.RongYunTokenTempService;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * 融云临时账户服务层
 * @author dzy
 */
@Service
@RequiredArgsConstructor
public class RongYunTokenTempServiceImpl implements RongYunTokenTempService {

    private final IdentifierGenerator identifierGenerator;
    private final RongYunTokenTempManager rongYunTokenTempManager;

    private final RemoteRongyunClient remoteRongyunClient;

    /**
     * 获取唯一融云Token值
     * @author dzy
     */
    @Override
    public RongYunTokenTempEntity getRongYunToken() {

        RongYunTokenTempEntity entity = new RongYunTokenTempEntity();

        // Redisson读取临时融云TOKEN
        RedissonClient redisson = RedisUtils.getClient();
        RQueue<RongYunTokenTempEntity> queue = redisson.getQueue(RongYunTokenConfig.RONGYUN_TOKEN_KEY);
        if (Objects.nonNull(queue) && queue.size() > 0) {
            entity = queue.poll();
            if (Objects.equals(YesNoNumberEnum.NO.getCode(), entity.getStatus())) {
                rongYunTokenTempManager.update(entity);
            }
        } else {
            entity = this.httpGetRongYunToken();
            if (Objects.isNull(entity)) {
                CommonErrors.BAD_REQUEST.check(false, MessageUtils.message("chat.rongyun.token.is.not.blank"));
            }
            if (Objects.equals(YesNoNumberEnum.NO.getCode(), entity.getStatus())) {
                rongYunTokenTempManager.update(entity);
            }
        }

        return entity;
    }

    /**
     * 更新融云Token内容
     * @author dzy
     */
    @Override
    public void refreshRongYunToken() {
        List<RongYunTokenTempEntity> list = rongYunTokenTempManager.selectList();
        if (CollectionUtil.isNotEmpty(list) && list.size() > 0) {
            // 读取一个临时token将剩余token更新到缓存中
            RedissonClient redisson = RedisUtils.getClient();
            RQueue<RongYunTokenTempEntity> queue = redisson.getQueue(RongYunTokenConfig.RONGYUN_TOKEN_KEY);
            queue.clear();
            list.forEach(item -> {
                queue.add(item);
            });
        }
    }

    /**
     * 通过请求获取融云TOKEN
     * @author dzy
     */
    @Override
    public RongYunTokenTempEntity httpGetRongYunToken() {
        // 数据库不存在 临时融云token
        Long userId = identifierGenerator.nextId(null).longValue();
        RongYunTokenTempEntity entity = new RongYunTokenTempEntity();
        entity.setId(userId);
        entity.setStatus(1);
        R<String> result = remoteRongyunClient.registUser(userId.toString(), "新用户", "");
        if (result.getCode() == 200 && StringUtils.isNotEmpty(result.getData())) {
            entity.setRongyunToken(result.getData());
        }
        return entity;
    }



    /**
     * 预生成融云token
     * @author dzy
     */
    @Override
    public boolean createRongYunTemp(Integer number) {
        CommonErrors.BAD_REQUEST.check(number <= 1000, "数量一次不能超过1000个");
        try {
            // 生成TOKEN集合
            List<RongYunTokenTempEntity> list = new ArrayList<>();

            // 创建线程池，其中参数5表示线程池中最多有5个线程
            ExecutorService executorService = Executors.newFixedThreadPool(10);

            int count = number / 200;
            int remainder = number % 200;

            // 计算每次生成200个的方法
            for (int i = 0; i < count; i++) {
                Semaphore semaphore = new Semaphore(0);
                for (int j = 0; j < RongYunTokenConfig.RONGYUN_COUNT; j++) {
                    // 多线程生成临时融云TOKEN
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                threadRongYunToken(list);
                            } finally {
                                // 执行完任务后，释放许可证
                                semaphore.release();
                            }
                        }
                    });
                }
                semaphore.acquire(RongYunTokenConfig.RONGYUN_COUNT);

                // 暂停1秒判断
                if(i < count - 1) {
                    Thread.sleep(1000);
                }
                if (i == count - 1 && remainder > 0) {
                    Thread.sleep(1000);
                }
            }

            // 余数生成方式
            Semaphore semaphore = new Semaphore(0);
            for (int i = 0; i < remainder; i++) {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            threadRongYunToken(list);
                        } finally {
                            // 执行完任务后，释放许可证
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(remainder);

            // 关闭线程池
            executorService.shutdown();

            boolean flag = rongYunTokenTempManager.saveBatch(list);
            if (flag) {
                this.refreshRongYunToken();
            }
            return flag;
        } catch (Exception e) {
            return false;
        }
    }

    private void threadRongYunToken(List<RongYunTokenTempEntity> list) {
        // 数据库不存在 临时融云token
        Long userId = identifierGenerator.nextId(null).longValue();
        R<String> result = remoteRongyunClient.registUser(userId.toString(), "新用户", "");
        if (result.getCode() == 200 && StringUtils.isNotEmpty(result.getData())) {
            RongYunTokenTempEntity entity = new RongYunTokenTempEntity();
            entity.setId(userId);
            entity.setRongyunToken(result.getData());
            entity.setStatus(0);
            list.add(entity);
        }
    }

    /**
     * 预生成融云token测试
     * @author dzy
     */
    @Override
    public boolean createRongYunTempTest(Integer number) {
        try {
            // 生成TOKEN集合
            List<RongYunTokenTempEntity> list = new ArrayList<>();

            // 创建线程池，其中参数5表示线程池中最多有5个线程
            ExecutorService executorService = Executors.newFixedThreadPool(10);

            int count = number / 200;
            int remainder = number % 200;

            // 计算每次生成200个的方法
            for (int i = 0; i < count; i++) {
                Semaphore semaphore = new Semaphore(0);
                for (int j = 0; j < RongYunTokenConfig.RONGYUN_COUNT; j++) {
                    // 多线程生成临时融云TOKEN
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                threadRongYunTokenTest(list);
                            } finally {
                                // 执行完任务后，释放许可证
                                semaphore.release();
                            }
                        }
                    });
                }
                semaphore.acquire(RongYunTokenConfig.RONGYUN_COUNT);
            }

            // 余数生成方式
            Semaphore semaphore = new Semaphore(0);
            for (int i = 0; i < remainder; i++) {
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            threadRongYunTokenTest(list);
                        } finally {
                            // 执行完任务后，释放许可证
                            semaphore.release();
                        }
                    }
                });
            }
            semaphore.acquire(remainder);
            // 关闭线程池
            executorService.shutdown();

            boolean flag = rongYunTokenTempManager.saveBatch(list);
            if (flag) {
                this.refreshRongYunToken();
            }
            return flag;
        } catch (Exception e) {
            return false;
        }

    }

    private void threadRongYunTokenTest(List<RongYunTokenTempEntity> list) {
        // 数据库不存在 临时融云token
        Long userId = identifierGenerator.nextId(null).longValue();
        RongYunTokenTempEntity entity = new RongYunTokenTempEntity();
        entity.setId(userId);
        entity.setRongyunToken("+Knvj2x7Bl5e63vgZJBFLztay2HwVqvvtIKfmQCzccfEAC0z9u@dfav.cn.rongnav.com;dfav.cn.rongcfg.com");
        entity.setStatus(0);
        list.add(entity);
    }

}
